package org.kazuhiko.rpg.server.task;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class TaskQueue
{
	private static final Logger logger = LoggerFactory.getLogger( TaskQueue.class );
	
	private static final TaskQueue INSTANCE = new TaskQueue();
	
	private ScheduledExecutorService service = Executors.newScheduledThreadPool( 1 );
	
	public static TaskQueue getTaskQueue()
	{
		return INSTANCE;
	}
	
	public TaskQueue()
	{
		//NO do nothing
	}
	
	public void push( final Task task )
	{
		service.submit( new Runnable()
		{	
			@Override
			public void run()
			{
				try
				{
					task.execute();
				}
				catch( Throwable t )
				{
					logger.error( "Error during task execution.", t );
				}
			}
		});
	}
	
	public void schedule( final ScheduledTask task )
	{
		schedule( task, task.getDelay() );
	}
	
	public void schedule( final ScheduledTask task, final long delay )
	{
		logger.trace( "Scheduled task {} with delay {}", task, delay );
		service.schedule( new Runnable()
		{	
			@Override
			public void run()
			{
				long start = System.currentTimeMillis();
				try
				{
					task.execute();
				}
				catch( Throwable t )
				{
					logger.error( "Error during task execution.", t );
				}
				
				if( !task.isRunning() )
				{
					return;
				}
				
				long elapsed = System.currentTimeMillis() - start;
				long waitFor = task.getDelay() - elapsed;
				if( waitFor < 0 )
				{
					waitFor = 0;
				}
				
				schedule( task, waitFor );
			}
		}, delay, TimeUnit.MILLISECONDS );
	}
}
